package com.shijunhao.graduation.aspect;

import com.alibaba.fastjson.JSON;
import com.shijunhao.graduation.annotations.OperationLog;
import com.shijunhao.graduation.domain.entity.OrgUser;
import com.shijunhao.graduation.domain.entity.SystemOperationLog;
import com.shijunhao.graduation.event.OperationLogEvent;
import com.shijunhao.graduation.service.business.IBusinessUserInfoService;
import com.shijunhao.graduation.utils.ServletUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author: shijunhao
 * @date: 2022/3/15 22:41
 * @description:
 */
@Aspect
@Component
public class OperationLogAspect {
    private final int OPERA_INFO_LENGTH = 2048;
    private final IBusinessUserInfoService businessUserInfoService;

    private final ApplicationEventPublisher applicationEventPublisher;

    public OperationLogAspect(IBusinessUserInfoService businessUserInfoService, ApplicationEventPublisher applicationEventPublisher) {
        this.businessUserInfoService = businessUserInfoService;
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @AfterThrowing(value = "@annotation(log)", throwing = "throwable")
    public void throwException(JoinPoint joinPoint, OperationLog log, Throwable throwable) {
        SystemOperationLog entity = getLog(joinPoint, log);
        entity.setIsSucceed(false);
        String resStr = JSON.toJSONString(throwable);
        entity.setResult(resStr.substring(0,Math.min(resStr.length(),OPERA_INFO_LENGTH)));
        applicationEventPublisher.publishEvent(new OperationLogEvent(entity));
    }

    @AfterReturning(value = "@annotation(log)", returning = "result")
    public void afterReturn(JoinPoint joinPoint, OperationLog log, Object result) {
        SystemOperationLog entity = getLog(joinPoint, log);
        entity.setIsSucceed(true);
        String resStr = JSON.toJSONString(result);
        entity.setResult(resStr.substring(0,Math.min(resStr.length(),OPERA_INFO_LENGTH)));
        applicationEventPublisher.publishEvent(new OperationLogEvent(entity));
    }

    private SystemOperationLog getLog(JoinPoint joinPoint, OperationLog log) {
        SystemOperationLog entity = new SystemOperationLog();
        Object[] args = joinPoint.getArgs();
        boolean isFileUpload = false;
        for(Object arg:args){
            if(arg instanceof MultipartFile){
                entity.setArgs("文件上传");
                isFileUpload = true;
            }
        }
        if(!isFileUpload){
            String argsStr = JSON.toJSONString(args);
            entity.setArgs(argsStr.substring(0,Math.min(argsStr.length(),OPERA_INFO_LENGTH)));
        }

        //设置用户相关信息
        OrgUser user = businessUserInfoService.getCurrentUser();
        entity.setUsername(user.getUsername());
        //设置用户填写的信息
        entity.setDescription(log.description());
        entity.setTarget(log.target());
        entity.setType(log.type());
        //设置请求信息
        HttpServletRequest request = ServletUtils.getRequest();
        entity.setRequestUri(request.getRequestURI());
        entity.setRequestMethod(request.getMethod());
        //设置基本信息
        entity.setDelete(false);
        entity.setCreateBy(user.getId());
        entity.setUpdateBy(user.getId());
        Date now = new Date();
        entity.setCreateDate(now);
        entity.setUpdateDate(now);
        return entity;
    }
}
